<template>
  <div class="app-container">
    <el-row :gutter="20">
      <el-col :span="4" :xs="24">
        <div class="head-container">
          <el-input
            v-model.trim="deptName"
            placeholder="请输入部门名称"
            clearable
            prefix-icon="Search"
            style="margin-bottom: 20px"
          />
        </div>
        <div class="head-container">
          <el-tree
            :data="deptOptions"
            :props="{ label: 'label', children: 'children' }"
            :expand-on-click-node="false"
            :filter-node-method="filterNode"
            ref="deptTreeRef"
            node-key="id"
            highlight-current
            default-expand-all
            @node-click="handleNodeClick"
          />
        </div>
      </el-col>
      <el-col :span="20" :xs="24">
        <el-form
          :model="queryParams"
          ref="queryRef"
          :inline="true"
          v-show="showSearch"
          label-width="70px"
        >
          <el-form-item label="用户账号" prop="userName">
            <el-input
              v-model="queryParams.userName"
              placeholder="请输入用户账号"
              clearable
              @keyup.enter="handleQuery"
            />
          </el-form-item>
          <el-form-item label="用户姓名" prop="nickName">
            <el-input
              v-model="queryParams.nickName"
              placeholder="请输入用户姓名"
              clearable
              @keyup.enter="handleQuery"
            />
          </el-form-item>
          <el-form-item label="手机号码" prop="phonenumber">
            <el-input
              v-model="queryParams.phonenumber"
              placeholder="请输入手机号码"
              clearable
              @keyup.enter="handleQuery"
            />
          </el-form-item>
          <el-form-item label="用户状态" prop="status">
            <el-select
              v-model="queryParams.status"
              placeholder="请选择用户状态"
              clearable
              @change="handleQuery"
            >
              <el-option
                v-for="dict in sys_normal_disable"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="删除状态" prop="delFlag">
            <el-select
              v-model="queryParams.delFlag"
              placeholder="请选择删除状态"
              clearable
              @change="handleQuery"
            >
              <el-option label="正常" value="0" />
              <el-option label="已删除" value="2" />
            </el-select>
          </el-form-item>
          <el-form-item label="创建时间" style="width: 300px">
            <el-date-picker
              v-model="dateRange"
              value-format="YYYY-MM-DD HH:mm:ss"
              type="daterange"
              range-separator="-"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
            />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
          </el-form-item>
        </el-form>

        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button
              type="primary"
              plain
              icon="Plus"
              @click="handleAdd"
              v-hasPermi="['web:base:system:user:add']"
            >
              新增
            </el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button
              type="success"
              plain
              icon="Edit"
              :disabled="single"
              @click="handleUpdate({})"
              v-hasPermi="['web:base:system:user:edit']"
            >
              修改
            </el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button
              type="danger"
              plain
              icon="Delete"
              :disabled="multiple"
              @click="handleDelete({})"
              v-hasPermi="['web:base:system:user:remove']"
            >
              删除
            </el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button
              type="info"
              plain
              icon="Upload"
              @click="handleImport"
              v-hasPermi="['web:base:system:user:import']"
            >
              导入
            </el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button
              type="warning"
              plain
              icon="Download"
              @click="handleExport"
              v-hasPermi="['web:base:system:user:export']"
            >
              导出
            </el-button>
          </el-col>
          <right-toolbar v-model:showSearch="showSearch" @query-table="getList" />
        </el-row>

        <el-table
          v-loading="loading"
          :data="userList"
          height="640"
          @selection-change="handleSelectionChange"
        >
          <el-table-column type="selection" width="50" align="center" />
          <el-table-column label="用户编号" align="center" prop="userId" />
          <el-table-column label="用户账号" align="center" prop="userName" />
          <el-table-column label="用户姓名" align="center" prop="nickName" />
          <el-table-column label="部门" align="center" prop="dept.deptName" />
          <el-table-column label="手机号码" align="center" prop="phonenumber" />
          <el-table-column label="证件号码" align="center" prop="idno" show-overflow-tooltip />
          <el-table-column label="用户状态" align="center" width="80">
            <template #default="scope">
              <el-switch
                v-model="scope.row.status"
                active-value="0"
                inactive-value="1"
                inline-prompt
                style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949"
                active-text="正常"
                inactive-text="停用"
                :disabled="scope.row.userId === 1"
                @change="handleStatusChange(scope.row)"
              />
            </template>
          </el-table-column>
          <el-table-column label="删除状态" align="center" width="80">
            <template #default="{ row }">
              <el-tag v-if="row.delFlag === '0'" size="small" type="success"> 正常</el-tag>
              <el-tag v-if="row.delFlag === '2'" size="small" type="danger"> 已删除</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
          <el-table-column label="操作" align="center" width="180">
            <template #default="scope">
              <div v-if="scope.row.delFlag === '2'">
                <el-tooltip content="恢复账号" placement="top">
                  <el-button
                    link
                    type="primary"
                    icon="RefreshLeft"
                    @click="handleRecovery(scope.row)"
                    v-hasPermi="['web:base:system:user:recovery']"
                  />
                </el-tooltip>
              </div>
              <div v-if="scope.row.userId !== 1 && scope.row.delFlag === '0'">
                <el-tooltip content="修改基本信息" placement="top">
                  <el-button
                    link
                    type="primary"
                    icon="Edit"
                    @click="handleUpdate(scope.row)"
                    v-hasPermi="['web:base:system:user:edit']"
                  />
                </el-tooltip>
                <el-tooltip content="修改证件号码" placement="top">
                  <el-button
                    link
                    type="primary"
                    icon="Postcard"
                    @click="handleUpdateIdno(scope.row)"
                    v-hasPermi="['web:base:system:user:editIdno']"
                  />
                </el-tooltip>
                <el-tooltip content="删除" placement="top">
                  <el-button
                    link
                    type="primary"
                    icon="Delete"
                    @click="handleDelete(scope.row)"
                    v-hasPermi="['web:base:system:user:remove']"
                  />
                </el-tooltip>
                <el-tooltip content="重置密码" placement="top">
                  <el-button
                    link
                    type="primary"
                    icon="Key"
                    @click="handleResetPwd(scope.row)"
                    v-hasPermi="['web:base:system:user:resetPwd']"
                  />
                </el-tooltip>
                <el-tooltip content="分配角色" placement="top">
                  <el-button
                    link
                    type="primary"
                    icon="CircleCheck"
                    @click="handleAuthRole(scope.row)"
                    v-hasPermi="['web:base:system:user:edit']"
                  />
                </el-tooltip>
              </div>
            </template>
          </el-table-column>
        </el-table>
        <pagination
          v-show="total > 0"
          :total="total"
          v-model:page="pageParams.pageNum"
          v-model:limit="pageParams.pageSize"
          @pagination="getList"
        />
      </el-col>
    </el-row>

    <el-dialog
      :title="title"
      v-model="open"
      width="600px"
      append-to-body
      :close-on-press-escape="false"
      :close-on-click-modal="false"
    >
      <el-form :model="form" :rules="rules" ref="userRef" label-width="80px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="用户姓名" prop="nickName">
              <el-input v-model="form.nickName" placeholder="请输入用户姓名" maxlength="30" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="归属部门" prop="deptId">
              <el-tree-select
                v-model="form.deptId"
                :data="deptOptions"
                :props="{ value: 'id', label: 'label', children: 'children' }"
                value-key="id"
                placeholder="请选择归属部门"
                check-strictly
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="手机号码" prop="phonenumber">
              <el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row v-if="!form.userId">
          <el-col :span="12">
            <el-form-item label="用户账号" prop="userName">
              <el-input v-model="form.userName" placeholder="请输入用户账号" maxlength="30" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="用户密码" prop="password">
              <el-input
                v-model="form.password"
                placeholder="请输入用户密码"
                type="password"
                show-password
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col v-if="!form.userId" :span="24">
            <el-form-item label="证件号码" prop="idno">
              <el-input v-model="form.idno" placeholder="请输入证件号码" maxlength="20" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="用户性别">
              <el-select v-model="form.sex" placeholder="请选择">
                <el-option
                  v-for="dict in sys_user_sex"
                  :key="dict.value"
                  :label="dict.label"
                  :value="dict.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="用户状态">
              <el-radio-group v-model="form.status">
                <el-radio
                  v-for="dict in sys_normal_disable"
                  :key="dict.value"
                  :value="dict.value"
                  :label="dict.label"
                />
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="岗位">
              <el-select v-model="form.postIds" multiple placeholder="请选择">
                <el-option
                  v-for="item in postOptions"
                  :key="item.postId"
                  :label="item.postName"
                  :value="item.postId"
                  :disabled="item.status === '1'"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="角色">
              <el-select v-model="form.roleIds" multiple placeholder="请选择">
                <el-option
                  v-for="item in roleOptions"
                  :key="item.roleId"
                  :label="item.roleName"
                  :value="item.roleId"
                  :disabled="item.status === '1'"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="备注">
              <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>

    <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
      <el-upload
        ref="uploadRef"
        :limit="1"
        accept=".xlsx, .xls"
        :headers="upload.headers"
        :action="upload.url"
        :disabled="upload.isUploading"
        :on-progress="handleFileUploadProgress"
        :on-success="handleFileSuccess"
        :auto-upload="false"
        drag
      >
        <el-icon class="el-icon--upload">
          <upload-filled />
        </el-icon>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        <template #tip>
          <div class="el-upload__tip text-center">
            <span>仅允许导入xls、xlsx格式文件。</span>
            <el-link
              type="primary"
              :underline="false"
              style="font-size: 12px; vertical-align: baseline"
              @click="importTemplate"
            >
              下载模板
            </el-link>
          </div>
        </template>
      </el-upload>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitFileForm">确 定</el-button>
          <el-button @click="upload.open = false">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
  import { ref, watch, reactive, getCurrentInstance } from 'vue';
  import { useRouter } from 'vue-router';
  import { getToken } from '@/utils/auth';
  import {
    changeUserStatus,
    listUser,
    resetUserPwd,
    getPlainInfo,
    editIndo,
    delUser,
    getUser,
    updateUser,
    addUser,
    deptTreeSelect,
    userTemplate,
    exportUser,
    recoveryUser,
  } from '@/api/system/user';
  import { useDict } from '@/utils/dict';
  import { addFieldTimeRange, checkNumPassword } from '@/utils/base';
  import { ElMessageBox } from 'element-plus';
  import modal from '@/plugins/modal';
  import { debounce } from 'lodash-es';

  const router = useRouter();
  const { proxy } = getCurrentInstance();
  const { sys_normal_disable, sys_user_sex } = useDict('sys_normal_disable', 'sys_user_sex');

  const queryRef = ref(null);
  const deptTreeRef = ref(null);
  const userRef = ref(null);
  const userList = ref([]);
  const open = ref(false);
  const loading = ref(true);
  const showSearch = ref(true);
  const ids = ref([]);
  const single = ref(true);
  const multiple = ref(true);
  const total = ref(0);
  const title = ref('');
  const dateRange = ref([]);
  const deptName = ref('');
  const deptOptions = ref([]);
  const postOptions = ref([]);
  const roleOptions = ref([]);
  const upload = reactive({
    open: false,
    title: '',
    isUploading: false,
    headers: { Authorization: 'Bearer ' + getToken() },
    url: import.meta.env.VITE_APP_BASE_API + '/web/base/system/user/import',
  });

  const form = ref({});
  const pageParams = ref({
    pageNum: 1,
    pageSize: 20,
  });
  const queryParams = ref({
    userName: null,
    nickName: null,
    phonenumber: null,
    status: null,
    delFlag: null,
    deptId: null,
  });
  const rules = ref({
    userName: [
      { required: true, message: '用户账号不能为空', trigger: 'blur' },
      { min: 2, max: 20, message: '用户账号长度必须介于 2 和 20 之间', trigger: 'blur' },
    ],
    nickName: [{ required: true, message: '用户姓名不能为空', trigger: 'blur' }],
    password: [{ required: true, validator: debounce(checkNumPassword, 500), trigger: 'change' }],
    deptId: [{ required: true, message: '归属部门不能为空', trigger: 'blur' }],
    phonenumber: [
      { required: true, message: '手机号码不能为空', trigger: 'blur' },
      { pattern: /^(?:0|86|\+86)?1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' },
    ],
    idno: [
      { required: true, message: '证件号码不能为空', trigger: 'blur' },
      {
        pattern: /^[1-9]\d{5}[1-2]\d{3}((0\d)|(1[0-2]))(([012]\d)|3[0-1])\d{3}(\d|X|x)$/,
        message: '请输入正确的证件号码',
        trigger: 'blur',
      },
    ],
  });

  watch(deptName, (val) => {
    deptTreeRef.value.filter(val);
  });

  function filterNode(value, data) {
    if (!value) return true;
    return data.label.indexOf(value) !== -1;
  }

  function getDeptTree() {
    return deptTreeSelect().then((res) => {
      deptOptions.value = res.data;
    });
  }

  function getList() {
    loading.value = true;
    listUser(addFieldTimeRange(queryParams.value, dateRange.value, 'createTime'), pageParams.value)
      .then((res) => {
        userList.value = res?.data?.records ?? [];
        total.value = res?.data?.total ?? 0;
      })
      .finally(() => {
        loading.value = false;
      });
  }

  function handleNodeClick(data) {
    queryParams.value.deptId = data.id;
    handleQuery();
  }

  function handleQuery() {
    pageParams.value.pageNum = 1;
    getList();
  }

  function resetQuery() {
    dateRange.value = [];
    queryRef.value?.resetFields();
    queryParams.value.deptId = null;
    deptTreeRef.value?.setCurrentKey(null);
    handleQuery();
  }

  function handleDelete(row) {
    const userIds = row?.userId ?? ids.value;
    modal
      .confirm('是否确认删除用户编号为"' + userIds + '"的数据项？')
      .then(function () {
        return delUser(userIds);
      })
      .then(() => {
        getList();
        modal.msgSuccess('删除成功');
      })
      .catch(() => {});
  }

  function handleRecovery(row) {
    const { userId, nickName } = row;
    modal
      .confirm(`是否恢复“${nickName}”的账号？`)
      .then(() => {
        return recoveryUser({ userId });
      })
      .then(() => {
        getList();
        modal.msgSuccess('恢复成功');
      })
      .catch(() => {});
  }

  function handleExport() {
    exportUser(
      addFieldTimeRange(queryParams.value, dateRange.value, 'createTime'),
      pageParams.value,
    );
  }

  function handleStatusChange(row) {
    let text = row.status === '0' ? '启用' : '停用';
    modal
      .confirm('确认要"' + text + '""' + row.userName + '"用户吗?')
      .then(function () {
        return changeUserStatus(row.userId, row.status);
      })
      .then(() => {
        modal.msgSuccess(text + '成功');
      })
      .catch(function () {
        row.status = row.status === '0' ? '1' : '0';
      });
  }

  function handleAuthRole(row) {
    const userId = row.userId;
    router.push('/system/user-auth/role/' + userId);
  }

  function handleResetPwd(row) {
    ElMessageBox.prompt('请输入"' + row.userName + '"的新密码', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      closeOnClickModal: false,
      inputPattern: /^.{5,25}$/,
      inputType: 'password',
      inputErrorMessage: '用户密码长度必须介于 5 和 25 之间',
    })
      .then(({ value }) => {
        resetUserPwd(row.userId, value).then(() => {
          modal.msgSuccess('修改成功');
        });
      })
      .catch(() => {});
  }

  function handleUpdateIdno(row) {
    getPlainInfo(row.userId).then((res) => {
      const userIdno = res.data.idno;
      ElMessageBox.prompt('请输入"' + row.userName + '"的新证件号码', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputValue: userIdno,
        closeOnClickModal: false,
        inputPattern: /^[1-9]\d{5}[1-2]\d{3}((0\d)|(1[0-2]))(([012]\d)|3[0-1])\d{3}(\d|X|x)$/,
        inputErrorMessage: '请输入正确的证件号码',
      })
        .then(({ value }) => {
          editIndo(row.userId, value).then(() => {
            modal.msgSuccess('修改成功');
            getList();
          });
        })
        .catch(() => {});
    });
  }

  function handleSelectionChange(selection) {
    ids.value = selection.map((item) => item.userId);
    single.value = selection.length !== 1;
    multiple.value = !selection.length;
  }

  function handleImport() {
    upload.title = '用户导入';
    upload.open = true;
  }

  function importTemplate() {
    userTemplate();
  }

  const handleFileUploadProgress = () => {
    upload.isUploading = true;
  };

  const handleFileSuccess = (response, file) => {
    upload.open = false;
    upload.isUploading = false;
    proxy.$refs['uploadRef'].handleRemove(file);
    proxy.$alert(
      "<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
        response.msg +
        '</div>',
      '导入结果',
      { dangerouslyUseHTMLString: true },
    );
    getList();
  };

  /** 提交上传文件 */
  function submitFileForm() {
    proxy.$refs['uploadRef'].submit();
  }

  /** 重置操作表单 */
  function reset() {
    form.value = {
      userId: undefined,
      deptId: undefined,
      userName: undefined,
      nickName: undefined,
      password: undefined,
      phonenumber: undefined,
      email: undefined,
      sex: undefined,
      status: '0',
      remark: undefined,
      postIds: [],
      roleIds: [],
      idno: undefined,
    };
    userRef.value?.resetFields();
  }

  /** 取消按钮 */
  function cancel() {
    open.value = false;
    reset();
  }

  function handleAdd() {
    reset();
    getUser().then((res) => {
      postOptions.value = res.posts;
      roleOptions.value = res.roles;
      title.value = '添加用户';
      open.value = true;
    });
  }

  function handleUpdate(row) {
    reset();
    const userId = row?.userId ?? ids.value;
    getUser(userId).then((res) => {
      form.value = res.data;
      postOptions.value = res.posts;
      roleOptions.value = res.roles;
      form.value.postIds = res.postIds;
      form.value.roleIds = res.roleIds;
      form.value.password = '';
      title.value = '修改用户';
      open.value = true;
    });
  }

  function submitForm() {
    userRef.value.validate((valid) => {
      if (valid) {
        if (form.value.userId) {
          updateUser(form.value).then(() => {
            modal.msgSuccess('修改成功');
            open.value = false;
            getList();
          });
        } else {
          addUser(form.value).then(() => {
            modal.msgSuccess('新增成功');
            open.value = false;
            getList();
          });
        }
      }
    });
  }

  getDeptTree();
  getList();
</script>
